
package genmai

import (
    "golang.org/x/crypto/ssh"
    "time"
    "bytes"
	"log"
	"os/exec"
	"strings"
    sandbox "main/genmai/Sandbox"
    // inter "main/genmai/Interpreter"
    "fmt"
)

type
ExplorerConfigBaseLine struct {
    FormatVer           int
    Id                  string
    Belong              string
    PocHazardLevel      string
    Source              string
    Power               string
    SiteInfo            SiteInfo
    SiteRequests        SiteRequests
}

type
ExplorerBaseLine struct {
    ExplorerCommon
    /* */
    //EkConfigParser  ConfigParserBase
    //EkConfig        ExplorerConfigBaseLine
    /* */
    EkSandbox       sandbox.SandboxBase
    /* */
    isSetup             bool
    Passwd          string
}


///////////////////////////////
// ExplorerBaseLine functions
func
(ek *ExplorerBaseLine)GetExplorerConfigBaseLine() (config *ExplorerConfigBaseLine, rc error) {
    cf, ret := ek.ExplorerCommon.EcConfig.(*ExplorerConfigBaseLine)
    /* */
    if (true == ret) {
        rc = nil
    } else {
        // TODO: ERR_CONVERSION_FAILED
    }

    config = cf
    /* */
    return config, rc
}

func
(ek *ExplorerBaseLine)SetupSandbox(sb sandbox.SandboxBase) {
    ek.EkSandbox    = sb
    /* */
    ek.isSetup      = true
}

func
(ek *ExplorerBaseLine)EexcBaseline(execPoc string,
                                  args ...string  ) string {
	cmd := exec.Command(execPoc,args...)
	var stdout, stderr bytes.Buffer
	cmd.Stdout = &stdout // 标准输出
	cmd.Stderr = &stderr // 标准错误
	err := cmd.Run()
	outStr, errStr := string(stdout.Bytes()), string(stderr.Bytes())
	if len(errStr)!=0{
		fmt.Printf(errStr)
	}
	outStr=strings.TrimSpace(outStr)
	if err != nil {
		log.Fatalf("cmd.Run() failed with %s\n", errStr)
	}
    return outStr

}


func
(ek *ExplorerBaseLine)HPowerEexcBaseline(exec string,passwd string,args ...string)(result string){
    sshHost := "127.0.0.1"

    sshUser := "root"

    sshPassword := passwd

    sshType := "password"

    sshPort := 22

    //创建sshp登陆配置

    config := &ssh.ClientConfig{

        Timeout:         5*time.Second,//ssh 连接time out 时间一秒钟, 如果ssh验证错误 会在一秒内返回

        User:            sshUser,

        HostKeyCallback: ssh.InsecureIgnoreHostKey(), //这个可以, 但是不够安全

        //HostKeyCallback: hostKeyCallBackFunc(h.Host),

    }

    //
    var command string
    for i:=0;i<len(args);i++{
        command=command+args[i]+" "
    }
    command=exec+" "+command
    if sshType == "password" {

        config.Auth = []ssh.AuthMethod{ssh.Password(sshPassword)}

    }

    //dial 获取ssh client

	addr := fmt.Sprintf("%s:%d", sshHost, sshPort)

    sshClient, err := ssh.Dial("tcp", addr, config)

    if err != nil {

        BaseLineError:="Error: Baseline high power connect fail,"
        fmt.Printf("%c[%d;%d;%dm%s%c[0m", 0x1B, 0, 0, 31, BaseLineError, 0x1B)
        fmt.Printf("%c[%d;%d;%dm%s%c[0m\n", 0x1B, 0, 0, 31, err, 0x1B)
        log.Fatal("Error: Baseline high power connect fail,",err)


    }

    defer sshClient.Close()

    //创建ssh-session

    session, err := sshClient.NewSession()

    if err != nil {

        fmt.Println("Baseline session fail,",err)
        log.Fatal("Creat ssh session fail,",err)
        
    

    }

    defer session.Close()

    //执行远程命令
    combo,err := session.CombinedOutput(command)

    if err != nil {
        BaseLineErr:="Baseline high power cmd fail"
        fmt.Printf("%c[%d;%d;%dm%s%c[0m", 0x1B, 0, 0, 31, BaseLineErr, 0x1B)
        fmt.Printf("%c[%d;%d;%dm%s%c[0m\n", 0x1B, 0, 0, 31, err, 0x1B)
        log.Fatal("Baseline high power cmd fail",err," ",command)
        
    }
    log.Println("Baseline exec successfully")
    defer session.Close()
    result=string(combo)
    return result
}

//func
//(ek *ExplorerBaseLine)Explore() (rc error) {
//}

///////////////////////////////
// override ExplorerBase functions
func
(ek *ExplorerBaseLine)Explore() (expvul VulnInfoCommon, rc error) {
    config, rc_t := ek.GetExplorerConfigBaseLine()
    rc = rc_t
    if (nil != rc) {
        A_DEBUG_ERROR("Explore()->GetExplorerConfigBaseLine() "+
                      "error! rc = ", rc                    )
        /* */
        return VulnInfoCommon{}, rc
    }

    ///////////////
    // starting explore
    var vul string
    for _, im := range config.SiteRequests.ImArray {
        if config.Power=="root"{
            if len(ek.Passwd)!=0{
                vul=ek.HPowerEexcBaseline(im.Exec,ek.Passwd,im.Args...)
            }else{
                infoWarn:="BaseLine warning: "+config.Id+" High power password is none "+",Can't use for high privilege baseline scan"
                fmt.Printf("%c[%d;%d;%dm%s%c[0m\n", 0x1B, 0, 0, 33, infoWarn, 0x1B)
                log.Println("warning:",config.Id,"High power password is none","Can't use for high privilege baseline scan")
                return
            }
        }else{
            vul=ek.EexcBaseline(im.Exec, im.Args...)
        }
        for i:=0;i<len(config.SiteRequests.Inter);i++{
            if vul==config.SiteRequests.Inter[i]{
                infoNonExis:="BaseLine info: "+config.Id+" non-existent"
                fmt.Printf("%c[%d;%d;%dm%s%c[0m\n", 0x1B, 0, 0, 34, infoNonExis, 0x1B)

                return
            }
        }
        /* */
    } // for _, im ...
    expvul.VICId             = config.Id
    expvul.VICBelong         = config.Belong
    expvul.VICPocHazardLevel = config.PocHazardLevel
    expvul.VICSource         = config.Source
    expvul.VICSiteInfo       = config.SiteInfo
    expvul.VICSiteRequests   = config.SiteRequests

    // ending explore
    ///////////////

    return expvul, nil
}

///////////////////////////////
// override functions